/*
 * rgb_led.c
 *
 * Created: 2012-12-16 21:04:12
 *  Author: prog
 */ 

/*
#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0x01 << (x))
*/

// includes
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>

// definition border of led values
#define LED_PERIOD_MAX 255
#define LED_PERIOD_MIN 0
#define LED_NO 3

// definition of pins
uint8_t led_pin[LED_NO][2] = { {&PORTB, PB0} , {&PORTB, PB1} , {&PORTB, PB2} };

// union for easy access to value of variable
typedef union {
	uint8_t led[3];
	struct {
		uint8_t r,g,b;
	};
} rgb_union_t;

// variables
rgb_union_t EEMEM ee_rgb;		// eeprom data duty
rgb_union_t rgb_new, rgb_act;	// ram data duty
char value_mode =0;				// 
uint8_t led_period =0;

// variable address in eeprom
char address_mode = 0;			// address for value_mode
char address_duty = 1;			// address for ee_rgb union/struct

// function to set certain bits
void lightOn(volatile uint8_t *port, uint8_t mask) {
	*port |= _BV(mask);
}
void lightOff(volatile uint8_t *port, uint8_t mask) {
	*port &= ~_BV(mask);
}

// initialize uC
void init ()
{
	// setup osc
	// setup ports
	DDRB = 0xff;
	PORTB = 0x00;
	// setup timer
}

// configure interrupts 
void int_en()
{
	// start timer
	// en interrupts
	sei();
}

// simplyfy access eeprom
void read_eeprom_duty()
{
	eeprom_read_block(&rgb_act, &ee_rgb, sizeof(rgb_union_t) );
}
void write_eeprom_duty()
{
	eeprom_write_block(&rgb_act, &ee_rgb, sizeof(rgb_union_t) );
}

// change LED pins on every timer tick
ISR(TIMER1_OVF_vect) 
{
	char i;
	led_period++;
	// correct led_period if needed
	if (led_period=LED_PERIOD_MAX)
		led_period=LED_PERIOD_MIN;

	if (led_period=LED_PERIOD_MIN)
	{
		for(i=0;i<LED_NO;i++)
			lightOn(led_pin[i][0], led_pin[i][1]);
	}
	// set led pin output for all leds
	for(i=0;i<LED_NO;i++)
	{
		if (led_period>rgb_act.led[i])
			lightOff(led_pin[i][0],led_pin[i][1]);
	}		
}


ISR(TIMER0_OVF_vect)
{
	
}

int main(void)
{
	// setup all used parts
	init();
	// interrupt enable
	int_en();
	
	//read last mode
	value_mode = eeprom_read_byte(address_mode);
	
	// prepare for certain mode
	switch (value_mode)
	{
		// mode 0 - simple change R-G-B
		case 0:
			read_eeprom_duty();
		default:
			eeprom_write_byte(address_mode,0);
			rgb_act.led[0] = 120;
			rgb_act.led[1] = 40;
			rgb_act.led[2] = 220;
			write_eeprom_duty();
	}
	
    while(1)
    {
        //TODO:: Please write your application code 
				
    }
}